package com.jrx.anytxn.customer.controller;

import com.jrx.anytxn.common.constant.Constants;
import com.jrx.anytxn.common.data.BusinessRes;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.JsonUtils;
import com.jrx.anytxn.common.uitl.SeqUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.config.CouponConfig;
import com.jrx.anytxn.customer.constant.CouponConstant;
import com.jrx.anytxn.customer.dto.bankcardinfo.BankCardInfoRes;
import com.jrx.anytxn.customer.dto.coupon.CouponReq;
import com.jrx.anytxn.customer.dto.creditinfo.AdjustLimitRecordRes;
import com.jrx.anytxn.customer.dto.customer.AddressInfoRes;
import com.jrx.anytxn.customer.dto.customer.CompanyInfoRes;
import com.jrx.anytxn.customer.dto.customer.ContactInfoRes;
import com.jrx.anytxn.customer.dto.customer.CustomerGroupInfoUpdateByCmsReq;
import com.jrx.anytxn.customer.dto.customer.CustomerLimitInfoRes;
import com.jrx.anytxn.customer.dto.customer.CustomerMobileUpdateByCmsReq;
import com.jrx.anytxn.customer.dto.customer.CustomerPageRes;
import com.jrx.anytxn.customer.dto.customer.CustomerRes;
import com.jrx.anytxn.customer.dto.customer.CustomerWholeInfoRes;
import com.jrx.anytxn.customer.dto.customer.NewCustomerRightsReissueReq;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.entity.CmLimitChangeLog;
import com.jrx.anytxn.customer.service.IBankCardService;
import com.jrx.anytxn.customer.service.ICouponInputService;
import com.jrx.anytxn.customer.service.ICustomerLimitInfoService;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.feign.api.request.ProductActiveReq;
import com.jrx.anytxn.feign.api.response.ProductActiveDto;
import com.jrx.anytxn.feign.api.service.IUserApiService;
import com.jrx.anytxn.feign.gateway.bean.ApiResponse;
import com.jrx.anytxn.feign.transaction.request.SendSmsReq;
import com.jrx.anytxn.feign.transaction.service.IAnyTxnTransactionService;
import com.jrx.anytxn.i18n.response.TxnRespResult;
import com.jrx.anytxn.param.entity.PrCreditLimitMapping;
import com.jrx.anytxn.param.service.limit.ICreditLimitMappingService;
import com.jrx.anytxn.param.utils.BizTypeProducts;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jrx.auth.filter.service.InfoService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 页面controller
 *
 * @author yf
 * date 2019/10/21 0021
 * @version V1.0
 **/
@Api(tags = "页面相关的客户管理api接口")
@RestController
@RequestMapping(value = "/customer")
public class CustomerController {
    private static Logger logger = LoggerFactory.getLogger(CustomerController.class);
    @Autowired
    private IBankCardService bankCardService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private ICustomerLimitInfoService customerLimitInfoService;

    @Autowired
    private InfoService infoService;

    @Autowired
    private ICreditLimitMappingService iCreditLimitMappingService;

    @Autowired
    private CouponConfig couponConfig;

    @Autowired
    private ICouponInputService couponInputService;

    @Autowired
    private ICustomerLimitInfoService iCustomerLimitInfoService;

    @Lazy
    @Autowired
    private IAnyTxnTransactionService anyTxnTransactionService;

    @Autowired
    private IUserApiService iUserApiService;

    @ApiOperation(value = "银行卡列表查询API", notes = "银行卡列表查询API")
    @GetMapping("/bankcard/getBankCardWithPage")
    public TxnRespResult<ArrayList<BankCardInfoRes>> getBankCardList(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<ArrayList<BankCardInfoRes>> bankResult = new TxnRespResult<>();
        String tenantId= String.valueOf(infoService.getUser().getProjectId());
        bankResult.getSuccess(bankCardService.getBankCardList(channel, customerId, tenantId));
        return bankResult;
    }

    @ApiOperation(value = "客户额度列表分页查询API", notes = "客户额度列表分页查询API")
    @GetMapping("/limit/getLimitWithPage")
    public TxnRespResult<ArrayList<CustomerLimitInfoRes>> getLimitList(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<ArrayList<CustomerLimitInfoRes>> result = new TxnRespResult<>();
        String tenantId=String.valueOf(infoService.getUser().getProjectId());
        result.getSuccess(customerLimitInfoService.getLimitList(customerId, tenantId));
        return result;
    }

    @ApiOperation(value = "客户基本信息查询", notes = "一级信息")
    @GetMapping(value = "/customerInfo/getCustomerByMobileOrIdNo")
    public TxnRespResult<ArrayList<CustomerPageRes>> getCustomerByMobileOrIdNo(@RequestParam String mobile, @RequestParam String idNo, @RequestParam String name,
                                                                               @RequestParam String userId,@RequestParam String customerId) {
        TxnRespResult<ArrayList<CustomerPageRes>> result = new TxnRespResult();
        try {
            String tenantId=String.valueOf(infoService.getUser().getProjectId());
            List<CustomerPageRes> customerList = customerService.getCustomerList(mobile, idNo, tenantId,name,userId,customerId);
             result.getSuccess((ArrayList)customerList);
        } catch (TxnBizException txn) {
            logger.error(txn.getErrMsg(),txn);
            result.getFail(txn.getErrCode(), txn.getErrMsg());
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            result.getFail(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
        }
        return result;
    }

    @ApiOperation(value = "客户详细信息信息查询", notes = "根据channel和customerId查询客户")
    @GetMapping(value = "/customerInfo/getCustomerDetail")
    public TxnRespResult<CustomerRes> getCustomerDetailByCondition(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<CustomerRes> result = new TxnRespResult();
        try {
            CustomerRes res = customerService.getCustomerByChannelAndCustomerIdAndTensnId(channel, customerId, String.valueOf(infoService.getUser().getProjectId()));
             result.getSuccess(res);
        } catch (TxnBizException txn) {
             result.getFail(txn.getErrCode(), txn.getErrMsg());
        } catch (Exception e) {
            result.getFail(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
        }
        return result;
    }


    @ApiOperation(value = "单位信息查询")
    @GetMapping(value = "/company/getWithPage")
    public TxnRespResult<ArrayList<CompanyInfoRes>> getCompanyWithPage(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<ArrayList<CompanyInfoRes>> result = new TxnRespResult();
        try {
            String tenantId=String.valueOf(infoService.getUser().getProjectId());
            result.getSuccess(customerService.getCompanyList(channel, customerId,tenantId));
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
           result.getFail(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
        }
        return result;
    }

    @ApiOperation(value = "地址信息查询", notes = "地址")
    @GetMapping(value = "/address/getWithPage")
    public TxnRespResult<ArrayList<AddressInfoRes>> getAddressWithPage(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<ArrayList<AddressInfoRes>> result = new TxnRespResult();
        try {
            String tenantId=String.valueOf(infoService.getUser().getProjectId());
            result.getSuccess(customerService.getAddressList(channel, customerId,tenantId));
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            result.getFail(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
        }
        return result;
    }

    @ApiOperation(value = "联系人信息查询", notes = "联系人")
    @GetMapping(value = "/contact/getWithPage")
    public TxnRespResult<ArrayList<ContactInfoRes>> getContactWithPage(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<ArrayList<ContactInfoRes>> result = new TxnRespResult();
        try {
            String tenantId=String.valueOf(infoService.getUser().getProjectId());
            result = result.getSuccess(customerService.getContactList(channel, customerId,tenantId));
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            result = result.getFail(TxnRespCode.BIZ_ERROR.getCode(), TxnRespCode.BIZ_ERROR.getUserTips());
        }
        return result;
    }

    @ApiOperation(value = "身份信息查询", notes = "根据channel和customerId查询客户")
    @GetMapping(value = "/customerInfo/getIdentity")
    public TxnRespResult<ArrayList<CustomerWholeInfoRes>> getIdentityByCondition(@RequestParam String channel, @RequestParam String customerId) {
        TxnRespResult<ArrayList<CustomerWholeInfoRes>> result = new TxnRespResult();
        try {
            result.getSuccess(customerService.getIdentityByChannelAndCustomerIdAndTenId(channel, customerId, String.valueOf(infoService.getUser().getProjectId())));
        } catch (TxnBizException txn) {
            result.getFail(txn.getErrCode(), txn.getErrMsg());
        } catch (Exception e) {
            result.getFail(TxnRespCode.BIZ_ERROR.getCode(), e);
        }
        return result;
    }

    @ApiOperation("查看调额记录")
    @GetMapping("/showAdjustLimitRecord/{customerId}/{channel}")
    public TxnRespResult<ArrayList<AdjustLimitRecordRes>> adjustLimitRecord(@PathVariable String customerId,@PathVariable String channel) throws TxnException {
        TxnRespResult<ArrayList<AdjustLimitRecordRes>> result=new TxnRespResult();
        result.getSuccess(customerLimitInfoService.getAdjustLimitRecord(String.valueOf(infoService.getUser().getProjectId()),customerId,channel));
        return result;
    }
    @ApiOperation(value = "客户额度信息查询", notes = "根据customerId和limitId查询客户")
    @GetMapping(value = "/limit/getCusLimitByCustomerIdAndLimitId/{organizationId}/{channel}/{customerId}/{limitId}")
    public TxnRespResult<CustomerLimitInfoRes>  getCustomerLimitByCustomerIdAndLimitId(@PathVariable String organizationId,@PathVariable String channel,@PathVariable String customerId,@PathVariable String limitId) throws TxnException {
        TxnRespResult<CustomerLimitInfoRes> result = new TxnRespResult();
        String tenantId = String.valueOf(infoService.getUser().getProjectId());
        result.getSuccess(customerLimitInfoService.selectCustomerLimitInfo(organizationId, channel, customerId,limitId,tenantId));
        return result;

    }

    @ApiOperation(value = "查询额度节点映射表limitId的list集合", notes = "查询额度节点映射表limitId的list集合")
    @GetMapping("/limit/getNormalLimitIdList")
    public TxnRespResult<List<String>> getNormalLimitIdList(@RequestParam String organizationId, @RequestParam String channel, @RequestParam String tenantId) {
        TxnRespResult<List<String>> result = new TxnRespResult<>();
        List<PrCreditLimitMapping> prCreditLimitMappingList = iCreditLimitMappingService.getLimitMappingByChannelAndOrgId(organizationId, channel, tenantId);
        result.getSuccess(prCreditLimitMappingList.stream().map(PrCreditLimitMapping::getLimitId).collect(Collectors.toList()));
        return result;
    }

    @ApiOperation(value = "修改客群", notes = "客群标识修改")
    @PostMapping(value = "/customerGroupInfoUpdateByCms")
    public TxnRespResult<String> customerGroupInfoUpdateByCms(@RequestBody CustomerGroupInfoUpdateByCmsReq req) throws TxnBizException {
        TxnRespResult<String> result = new TxnRespResult<>();
        String tenantId=String.valueOf(infoService.getUser().getProjectId());
        String customerId = req.getCustomerId();
        String channel = req.getChannel();
        String customerGroup = req.getCustomerGroup();
        String alterReason = req.getAlterReason();
        try {
            customerService.customerGroupInfoUpdateByCms(customerId,channel,tenantId,customerGroup,alterReason);
            result.getSuccess(customerGroup);
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.setData(customerGroup);
            result.getFail(e.getErrCode(), e.getErrMsg());
        }
        return result;
    }

    @ApiOperation(value = "修改手机号", notes = "手机号修改")
    @PostMapping(value = "/customerMobileUpdateByCms")
    public TxnRespResult<String> customerMobileUpdateByCms(@RequestBody CustomerMobileUpdateByCmsReq req) throws TxnBizException {
        TxnRespResult<String> result = new TxnRespResult<>();
        req.setTenantId(String.valueOf(infoService.getUser().getProjectId()));
        try {
            customerService.customerMobileUpdateByCms(req);
            result.getSuccess(null);
        } catch (TxnException e) {
            logger.error(e.getMessage(),e);
            result.getFail(e.getErrCode(), e.getErrMsg());
        }
        return result;
    }

    @ApiOperation(value = "补发优惠券", notes = "补发优惠券")
    @PostMapping(value = "/customerRightsReissue")
    public TxnRespResult<BusinessRes> customerRightsReissue(@RequestBody @Valid NewCustomerRightsReissueReq req) throws TxnBizException {
        TxnRespResult<BusinessRes> result = new TxnRespResult<>();
        CmCustomerSecondLevel customerSecondLevel = customerService.getSecondByMobileAndTenantId(req.getMobile(), Constants.DEFAULT_TENANT_ID);

        //校验客户是否激活
        checkUserActivity(req.getProductId(), customerSecondLevel.getChannel(), customerSecondLevel.getUserId());

        //组装发券入参数据
        CouponReq couponReq = generateCouponReq(customerSecondLevel);
        couponReq.setProductCode(req.getProductId());

        //是否重新授信客户
        boolean isReCreditCustomer = this.reCreditCustomerCheck(customerSecondLevel.getCustomerId(), req.getProductId());
        //是否兴安花产品
        boolean sendCouponForXAH = BizTypeProducts.XAH_PRODUCT.equals(req.getProductId());

        Map<String, String> activityMap = couponConfig.getProductId();
        String activityIds = null;

        if (sendCouponForXAH) {
            if (isReCreditCustomer) {
                activityIds = generateActivityIdsForProduct(activityMap, req.getProductId());
            } else {
                //兴安花首次激活情况，根据渠道发券
                String subChannel = customerSecondLevel.getSubChannel();
                //设置默认活动Id
                activityIds = couponConfig.getChannelMissing();
                if (StringUtils.isNotBlank(subChannel) && couponConfig.getCompatibleChannels().contains(subChannel)) {
                    logger.info("不与MGM互斥的渠道");
                    String activityId = couponConfig.getChannels().get(subChannel);
                    if (!StringUtils.isBlank(activityId)) {
                        activityIds = activityId;
                    }
                }
                //有推荐人编号--通过邀新渠道激活
                else if (StringUtils.isNotBlank(customerSecondLevel.getRecommenderCode())) {
                    logger.info("有推荐人编号,通过邀新渠道激活");
                    activityIds = couponConfig.getMGM();
                } else if (!StringUtils.isBlank(subChannel)) {
                    String activityId = couponConfig.getChannels().get(subChannel);
                    if (!StringUtils.isBlank(activityId)) {
                        activityIds = activityId;
                    }
                }
            }
        } else {
            activityIds = generateActivityIdsForProduct(activityMap, req.getProductId());
        }
        try {
            String[] activityIdsArr = activityIds.split(",");
            //是否补发成功标识
            boolean reissueFlag = false;
            for (String activityId : activityIdsArr) {
                logger.info("开始处理发券逻辑");
                couponReq.setActivityId(activityId);
                try {
                    couponInputService.grantCoupon(couponReq);
                    reissueFlag = true;
                } catch (TxnBizException txnBizException) {
                    logger.warn(txnBizException.getErrMsg());
                }
            }
            //补发成功且不为信用就医
            if (reissueFlag && !BizTypeProducts.PRODUCT_XYJY.equals(couponReq.getProductCode())) {
                generalSendSms(customerSecondLevel, CouponConstant.SMS_TYPE_GRANT_COUPON_RIGHTS, CouponConstant.MORE_COUPON_END_FIX);
            }
        } catch (TxnException txnException) {
            return result.getFail(txnException.getErrCode(), txnException.getErrMsg());
        }
        return result.getSuccess(new BusinessRes(1000, "优惠券已成功补发"));
    }

    private boolean reCreditCustomerCheck(String customerId, String productId) {
        boolean isReCreditCustomer = false;
        List<CmLimitChangeLog> limitChangeLogs = iCustomerLimitInfoService.queryChangeLogs(Constants.DEFAULT_TENANT_ID, customerId, productId);
        if (limitChangeLogs.size() > 1) {
            //若客户该产品变更记录大于1，则代表重新授信客户
            isReCreditCustomer = true;
        }
        return isReCreditCustomer;
    }

    private CouponReq generateCouponReq(CmCustomerSecondLevel cmCustomerSecondLevel) {
        logger.info("组装补发券必要入参数据");
        CouponReq req = new CouponReq();
        req.setType("0");
        req.setUserId(cmCustomerSecondLevel.getUserId());
        req.setChannel(cmCustomerSecondLevel.getChannel());
        req.setTenantId(cmCustomerSecondLevel.getTenantId());
        req.setCustomerId(cmCustomerSecondLevel.getCustomerId());
        return req;
    }

    private void generalSendSms(CmCustomerSecondLevel customerSecondLevel, String smsType, String rightsName) {
        logger.info("组装发送短信的必要参数");
        SendSmsReq req = new SendSmsReq();
        req.setCustomerId(customerSecondLevel.getCustomerId());
        req.setChannel(customerSecondLevel.getChannel());
        req.setTenantId(customerSecondLevel.getTenantId());
        req.setMobile(customerSecondLevel.getMobile());
        req.setSeqNo(SeqUtils.getRandomNumber(18));
        req.setSmsType(smsType);
        req.setLoanId(rightsName);
        anyTxnTransactionService.sendSms(req);
    }

    private void checkUserActivity(String productId, String channel, String userId) throws TxnBizException {
        ApiResponse<List<ProductActiveDto>> apiResponse = null;
        try {
            ProductActiveReq productActiveReq = new ProductActiveReq();
            productActiveReq.setProductId(productId);
            productActiveReq.setChannelNo(channel);
            productActiveReq.setUserId(userId);
            productActiveReq.setTenantId(Constants.DEFAULT_TENANT_ID);

            apiResponse = iUserApiService.activeInfoQuery(JsonUtils.toJSon(productActiveReq));
        } catch (Exception e) {
            e.printStackTrace();
        }

        List<ProductActiveDto> productActiveDtoList = apiResponse.getData();
        if (CollectionUtils.isEmpty(productActiveDtoList)) {
            logger.info("客户{}未激活产品，不进行发券", userId);
            throw new TxnBizException(9999, "客户未激活产品，不进行发券");
        }

        List<ProductActiveDto> activeProduct = productActiveDtoList
                .stream().filter(x -> "1".equals(x.getActiveFlag())).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(activeProduct)) {
            throw new TxnBizException(9999, "客户未激活产品，不进行发券");
        }
    }

    public String generateActivityIdsForProduct(Map<String, String> activityMap, String productId) throws TxnBizException {
        activityMap = couponConfig.getProductId();

        String activityIds = activityMap.get(productId);

        if (StringUtils.isEmpty(activityIds)) {
            logger.info("暂无产品{}发券的配置信息", productId);
            throw new TxnBizException("该产品的发券配置不存在");
        }
        return activityIds;
    }
}
